package service

import (
	"fmt"
	corev1 "k8s.io/api/core/v1"
	"sort"
	"strings"
	"time"
)

// dataSelector用于封装排序、过滤、分页的数据类型
type dataSelector struct {
	GenericDataList []DataCell
	DataSelect      *DataSelectQuery
}

//DataCell接口，用于各种资源List的类型转换，转后可以使用dataSelector的排序，过滤，分页方法
type DataCell interface {
	GetCreation() time.Time
	GetName() string
}

// 定义过滤和分页的结构体，过滤Name，分页Limit和Page
// Limit是单页的数据条数
// Page是第几页
type DataSelectQuery struct {
	Filter   *FilterQuery
	Paginate *PaginateQuery
}
type FilterQuery struct {
	Name string
}
type PaginateQuery struct {
	Limit int
	Page  int
}

//实现自定义结构的排序，需要重写Len、Swap、Less方法
//Len方法用于获取数组的长度
func (d *dataSelector) Len() int {
	return len(d.GenericDataList)
}

//Swap方法用于数据比较大小之后的位置变化
func (d *dataSelector) Swap(i, j int) {
	d.GenericDataList[i], d.GenericDataList[j] = d.GenericDataList[j], d.GenericDataList[i]
}

//Less方法用于比较大小
func (d *dataSelector) Less(i, j int) bool {
	a := d.GenericDataList[i].GetCreation()
	b := d.GenericDataList[j].GetCreation()
	//如果b的时间比a 的时间早，就返回true
	return b.Before(a)
}

//重写以上三个方法，使用sort.Sort进行排序
//而且从源码来看，Sort也是重写了上面三个方法.
func (d *dataSelector) Sort() *dataSelector {
	sort.Sort(d)
	return d
}

//Filter方法用于过滤数据，比较数据的Name属性，若包含，则返回
func (d *dataSelector) Filter() *dataSelector {
	//判断入参是否为空，若为空，则返回所有数据
	if d.DataSelect.Filter.Name == "" {
		return d
	}
	//若不为空，则按照入参Name进行过滤
	//声明一个新的数组，若name包含，则把数据放进属组，返回出去
	filteredList := []DataCell{}
	for _, value := range d.GenericDataList {
		//定义是否匹配的标签变量，默认是匹配
		matches := true
		objName := value.GetName()
		if !strings.Contains(objName, d.DataSelect.Filter.Name) {
			matches = false
			continue
		}
		if matches {
			filteredList = append(filteredList, value)
		}
	}
	d.GenericDataList = filteredList
	return d
}

//Pagination方法用于属组的分页，根据Limit和Page的传参，取一定范围内的数据，返回
func (d *dataSelector) Paginate() *dataSelector {
	//根据Limit和Page的入参，定义快捷变量
	limit := d.DataSelect.Paginate.Limit
	page := d.DataSelect.Paginate.Page
	//检验参数的合法性
	if limit <= 0 || page <= 0 || len(d.GenericDataList) == 0 {
		return d
	}
	//定义取数范围需要的startIndex和endIndex
	//举例，有个25个元素的数组，limit是10，page是3，startIndex是20，endIndex是29（实际上24）
	startIndex := limit * (page - 1)
	endIndex := limit * page
	//处理endIndex
	if endIndex >= len(d.GenericDataList) {
		endIndex = len(d.GenericDataList)
	}

	//// 如果只有一条数据，那么也是直接返回,否则下面的d.GenericDataList[0:0]的列表为空
	if startIndex == endIndex {
		return d
	}
	//取出指定范围的数据
	d.GenericDataList = d.GenericDataList[startIndex:endIndex]
	fmt.Printf("%d,%d", startIndex, endIndex)
	return d
}

//定义podCell，重写GetCreation和GetName方法后，可以进行数据转换

type podCell corev1.Pod

//重写DataCell接口的两个方法
func (p podCell) GetCreation() time.Time {
	return p.CreationTimestamp.Time
}

func (p podCell) GetName() string {
	return p.Name
}
